package put.cs.two.hied.netflix;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;

/**
 * @author Mateusz Chrominski
 * 
 */
public class TrainingSetWriter {

    private final String trainingSetDirPath;

    private final ProbeReader reader;

    private String outputDirectory;

    private String qualifyingFilePath;
    
    private String probeFilePath;
    
    private String qualifierResultFilePath;
    
    private String qualifierResult2FilePath;
    
    private String qualifierResult3FilePath;

    private BufferedWriter qualifierFile;
    
    private BufferedWriter qualifierResultFile;
    
    private BufferedWriter qualifierResult2File;
    
    private BufferedWriter qualifierResult3File;
    
    private BufferedWriter probeFile;

    public TrainingSetWriter(String trainingSetPath, ProbeReader reader) {
        this.trainingSetDirPath = trainingSetPath;
        this.reader = reader;
    }

    public void setQualifyingFilePath(String qualifyingFilePath) {
        this.qualifyingFilePath = qualifyingFilePath;
    }

    public void setQualifierResultFilePath(String qualifierResultFilePath) {
		this.qualifierResultFilePath = qualifierResultFilePath;
	}

	public void setProbeFilePath(String probeFilePath) {
		this.probeFilePath = probeFilePath;
	}

	public void setQualifierResultFile(BufferedWriter qualifierResultFile) {
		this.qualifierResultFile = qualifierResultFile;
	}

	public void setQualifierResult2File(BufferedWriter qualifierResult2File) {
		this.qualifierResult2File = qualifierResult2File;
	}

	public void setQualifierResult2FilePath(String qualifierResult2FilePath) {
		this.qualifierResult2FilePath = qualifierResult2FilePath;
	}

	public void rewrite(String outputDirectory) {
        this.outputDirectory = outputDirectory;
        System.out.println("Writing new training set, qualifierFile and probeFile...");
        try {
            qualifierFile = new BufferedWriter(new FileWriter(qualifyingFilePath));
            probeFile = new BufferedWriter(new FileWriter(probeFilePath));
            qualifierResultFile = new BufferedWriter(new FileWriter(qualifierResultFilePath));
            qualifierResult2File = new BufferedWriter(new FileWriter(qualifierResult2FilePath));
            qualifierResult3File = new BufferedWriter(new FileWriter(qualifierResult3FilePath));
            File inputDir = new File(trainingSetDirPath);
            File[] files = inputDir.listFiles();
            Arrays.sort(files);
            
            int i = 0;
            for (File file : files) {
            	//System.out.println("doFilter for file \"" + file.getName() + "\"");
                doFilter(file);
                i++;
                if (i % 1000 == 0) {
                    System.out.println(i + " files parsed");
                }
            }
            qualifierFile.close();
            probeFile.close();
            qualifierResultFile.close();
            qualifierResult2File.close();
            qualifierResult3File.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private void doFilter(File file) throws IOException {
        BufferedReader in = new BufferedReader(new FileReader(file.getCanonicalPath()));
        String line;
        String movieId = null;

        BufferedWriter out = getBufferedWriter(file);
        boolean first = true;
        boolean firstForProbe = true;
        while ((line = in.readLine()) != null) {
            if (!line.contains(":")) {
                TrainingSetEntry entry = new TrainingSetEntry(movieId);
                String[] words = line.split(",");
                entry.setUserId(words[0]);
                entry.setRating(words[1]);
                entry.setDate(words[2]);
                //if (!reader.hasEntry(entry)) {
                if(!reader.hasEntry(entry)) {
                    out.write(entry.toString());
                    out.write("\n");
                } else {
                    if (first) {
                        qualifierFile.write(movieId + ":\n");
                        qualifierResult2File.write(movieId + ":\n");
                        qualifierResult3File.write(movieId + ":\n");
                        first = false;
                    }
                    qualifierFile.write(entry.printWithoutRating() + "\n");
                    qualifierResultFile.write(entry.printWithMovieIdAndRating() + "\n");
                    qualifierResult2File.write(entry.toString() + "\n");
                    qualifierResult3File.write(entry.getRating() + "\n");
                }
                //probe
                if(reader.hasEntryInProbe(entry)) {
                	if(firstForProbe) {
                		probeFile.write(movieId + ":\n");
                		firstForProbe = false;
                	}
                	probeFile.write(entry.getUserId().toString() + "\n");
                }
            } else {
                movieId = ProbeReader.trim(line);
                out.write(line);
                out.write("\n");
            }
        }
        in.close();
        out.close();
    }

    private BufferedWriter getBufferedWriter(File file) throws IOException {
        String outputFilePath = outputDirectory + file.getName();
        File newFile = new File(outputFilePath);
        if (!newFile.exists()) {
            newFile.createNewFile();
        }
        BufferedWriter out = new BufferedWriter(new FileWriter(outputFilePath));
        return out;
    }

	public String getQualifierResult3FilePath() {
		return qualifierResult3FilePath;
	}

	public void setQualifierResult3FilePath(String qualifierResult3FilePath) {
		this.qualifierResult3FilePath = qualifierResult3FilePath;
	}

	public BufferedWriter getQualifierResult3File() {
		return qualifierResult3File;
	}

	public void setQualifierResult3File(BufferedWriter qualifierResult3File) {
		this.qualifierResult3File = qualifierResult3File;
	}
}